package fr.vvins.core.cms.page;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.ehcache.annotations.Cacheable;

import fr.vvins.core.cms.page.dto.BlockDto;
import fr.vvins.core.cms.page.dto.PageDto;
import fr.vvins.core.common.TechnicalException;
import fr.vvins.core.common.dto.DtoFactory;
import fr.vvins.core.common.dto.EntityDtoConverter;
import fr.vvins.core.page.dao.PageRepository;
import fr.vvins.core.page.entity.Block;
import fr.vvins.core.page.entity.Page;
import fr.vvins.core.page.entity.Zone;

public class PageManagerImpl implements PageManager {
	
	private final static Logger log = LoggerFactory.getLogger(PageManagerImpl.class);
	
	@Autowired
	private DtoFactory dtoFactory;
	
	@Autowired
	private EntityDtoConverter converter;
	
	@Autowired
	private PageRepository pageDao;

	private PageDto convertPage(Page entity) throws TechnicalException {
		PageDto dto = new PageDto();
		List<String> property = new ArrayList<String>();
		property.add("blocks");
		try {
			converter.convertEntityToDto(entity, dto, property);
			Map<Zone, Block> blocks = entity.getBlocks();
			if(blocks != null && !blocks.isEmpty()){
				Map<String, BlockDto> blocksDto = new HashMap<String,BlockDto>();
				for(Zone key : blocks.keySet()){
					BlockDto d = new BlockDto();
					converter.convertEntityToDto(blocks.get(key), d);
					blocksDto.put(key.getName(), d);
				}
				dto.setBlocks(blocksDto);
			}
		} catch (BeansException e) {
			throw new TechnicalException(TechnicalException.CONVERT, e.getMessage());
		}
		return dto;		
	}
	
	@Cacheable(cacheName="page")
	@Transactional
	public PageDto getPage(Integer id) throws TechnicalException, PageException {
		try {
			return convertPage(pageDao.findOne(id));
		} catch (Throwable e) {
			throw new TechnicalException(TechnicalException.CONVERT, e.getMessage());
		}
		
	}
	
	@Cacheable(cacheName="page")
	@Transactional
	public PageDto getPageByContent(String name, String contentKey) throws TechnicalException, PageException {
		PageDto dto = new PageDto();
		try {
			List<Page> pages = pageDao.findByNameAndContentKey(name, contentKey);
			if(pages != null && pages.size() > 0) {
				if(pages.size() > 1){
					log.warn("There are more than one page for this page. Return : " + pages.get(0).getId());
				}
				dto = convertPage(pages.get(0));
			} else {
				pages = pageDao.findDefaultByName(name);
				if(pages != null && pages.size() > 0) {
					if(pages.size() > 1){
						log.warn("There are more than one page for this page. Return : " + pages.get(0).getId());
					} 
					dto = convertPage(pages.get(0));
				} else {
					log.error("Page " + name + "not found for type "+ name + " and content " + contentKey);
					throw new PageException(PageException.NOT_FOUND, "Page " + name + "not found for type "+ name + " and content " + contentKey );
				}
			}
		} catch (BeansException e) {
			throw new TechnicalException(TechnicalException.CONVERT, e.getMessage());
		} catch (Throwable e) {
			throw new TechnicalException(TechnicalException.CONVERT, e.getMessage());
		}
		return dto;
	}


	@Cacheable(cacheName="page")
	@Transactional
	public PageDto getPage(String name) throws TechnicalException, PageException {
		PageDto dto = new PageDto();
		try {
			List<Page> pages = pageDao.findDefaultByName(name);
			if(pages != null && pages.size() > 0) {
				if(pages.size() > 1){
					log.warn("There are more than one page for this page. Return : " + pages.get(0).getId());
				} 
				dto = convertPage(pages.get(0));
			} else {
				log.error("No page found for name : " + name);
				throw new PageException(PageException.NOT_FOUND, "No page found for this name : " + name);
			}
		} catch (BeansException e) {
			throw new TechnicalException(TechnicalException.CONVERT, e.getMessage());
		} catch (Throwable e) {
			throw new TechnicalException(TechnicalException.CONVERT, e.getMessage());
		}
		return dto;
	}

	public DtoFactory getDtoFactory() {
		return dtoFactory;
	}

	public void setDtoFactory(DtoFactory dtoFactory) {
		this.dtoFactory = dtoFactory;
	}

	public EntityDtoConverter getConverter() {
		return converter;
	}

	public void setConverter(EntityDtoConverter converter) {
		this.converter = converter;
	}

	public PageRepository getPageDao() {
		return pageDao;
	}

	public void setPageDao(PageRepository pageDao) {
		this.pageDao = pageDao;
	}

}